package br.com.sgdee.util;

import java.sql.Connection;
import java.sql.SQLException;
import java.text.Normalizer;
import java.util.List;
import java.util.Map;

//import org.apache.commons.dbutils.QueryRunner;
//import org.apache.commons.dbutils.ResultSetHandler;
//import org.apache.commons.dbutils.handlers.ArrayHandler;
//import org.apache.commons.dbutils.handlers.BeanHandler;
//import org.apache.commons.dbutils.handlers.BeanListHandler;
//import org.apache.commons.dbutils.handlers.ColumnListHandler;
//import org.apache.commons.dbutils.handlers.MapListHandler;
import org.apache.commons.lang.StringUtils;

/**
 * Classe utilitaria.
 * 
 * @author TATA Consultancy Services do Brasil
 * 
 */
public class SQLUtil {
	/**
	 * default logger
	 */
	private static org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(SQLUtil.class);
	
	public static final String TRANSLATE_CONSULTA_POSTGRES = "TRANSLATE(UPPER(%s), 'áéíóúàèìòùãõâêîôôäëïöüçÁÉÍÓÚÀÈÌÒÙÃÕÂÊÎÔÛÄËÏÖÜÇ', 'aeiouaeiouaoaeiooaeioucAEIOUAEIOUAOAEIOOAEIOUC')";

	/**
	 * Executa uma consulta e retona vários objetos preenchidos.
	 * 
	 * @param conn connection
	 * @param sql instrucao sql
	 * @param classe classe java
	 * @param parametros lista de parametros
	 * @return List lista de objetos
	 * @throws SQLException exception
	 */
//	@SuppressWarnings("rawtypes")
//	public static List getList(Connection conn, String sql, Class classe, Object[] parametros) throws SQLException {
//		QueryRunner run = new QueryRunner();
//		ResultSetHandler bean = new BeanListHandler(classe);
//		return (List) run.query(conn, sql, parametros, bean);
//	}

	/**
	 * Executa uma consulta e retona vários objetos preenchidos.
	 * 
	 * @param conn connection
	 * @param sql instrução a ser executada
	 * @param parametros lista de parametros
	 * @return List lista de objetos
	 * @throws SQLException exception
	 */
//	@SuppressWarnings("rawtypes")
//	public static List getColumnList(Connection conn, String sql, Object[] parametros) throws SQLException {
//		QueryRunner run = new QueryRunner();
//		ResultSetHandler bean = new ColumnListHandler();
//		return (List) run.query(conn, sql, parametros, bean);
//	}

	/**
	 * Executa uma consulta e retona varias Maps com os campos preenchidos
	 * 
	 * @param conn connection
	 * @param sql instrução a ser executada
	 * @param parametros lista de parametros
	 * @return List lista de objetos
	 * @throws SQLException exception
	 */
//	@SuppressWarnings({ "rawtypes", "unchecked" })
//	public static List<Map> getMapList(Connection conn, String sql, Object[] parametros) throws SQLException {
//		logger.debug(sql);
//		QueryRunner run = new QueryRunner();
//		ResultSetHandler bean = new MapListHandler();
//		return (List<Map>) run.query(conn, sql, parametros, bean);
//	}

	/**
	 * Select simples. Retorna o objeto preenchido.
	 * 
	 * @param conn connection
	 * @param sql instrução a ser executada
	 * @param classe classe
	 * @param parametros lista de parametros
	 * @return List lista de objetos
	 * @throws SQLException exception
	 */
//	@SuppressWarnings("rawtypes")
//	public static Object getObject(Connection conn, String sql, Class classe, Object[] parametros) 
//		throws SQLException {
//		QueryRunner run = new QueryRunner();
//		ResultSetHandler bean = new BeanHandler(classe);
//		return run.query(conn, sql, parametros, bean);
//
//	}

	/**
	 * Select simples. Retorna Array de objetos.
	 * 
	 * @param conn connection
	 * @param sql instrução a ser executada
	 * @param parametros lista de parametros
	 * @return List lista de objetos
	 * @throws SQLException exception
	 */
//	public static Object[] getArray(Connection conn, String sql, Object[] parametros) 
//		throws SQLException {
//		QueryRunner run = new QueryRunner();
//		ResultSetHandler bean = new ArrayHandler();
//		return (Object[]) run.query(conn, sql, parametros, bean);
//
//	}

	/**
	 * Efetua um simples select retornando somento uma coluna.
	 * 
	 * @param conn connection
	 * @param sql instrução a ser executada
	 * @param parametros lista de parametros
	 * @return Objeto consultado
	 * @throws SQLException exception
	 */
//	public static Object getUniqueColumn(Connection conn, String sql, Object[] parametros) throws SQLException {
//		Object[] columns = getArray(conn, sql, parametros);
//		if (columns == null) {
//			return null;
//		}
//		return columns[0];
//	}

	/**
	 * Realiza INSERT, UPDATE ou DELETE com a os parâmetros informados.
	 * 
	 * @param conn connection
	 * @param sql instrução a ser executada
	 * @param params lista de parametros
	 * @return Objeto consultado
	 * @throws SQLException exception
	 */
//	public static int update(Connection conn, String sql, Object[] params) 
//		throws SQLException {
//		QueryRunner run = new QueryRunner();
//		return run.update(conn, sql, params);
//	}

	/**
	 * Realiza INSERT, UPDATE ou DELETE com a o parâmetro informado.
	 * 
	 * @param conn connection 
	 * @param sql instrução sql
	 * @param param parametro
	 * @throws SQLException exception
	 * @return numero de linhas atualizadas
	 */
//	public static int update(Connection conn, String sql, Object param) throws SQLException {
//		QueryRunner run = new QueryRunner();
//		return run.update(conn, sql, param);
//	}

	/**
	 * Realiza INSERT, UPDATE ou DELETE.
	 * 
	 * @param conn connection
	 * @param sql instrução a ser executada
	 * @throws SQLException exception
	 * @return numero de linhas atualizadas
	 */
//	public static int update(Connection conn, String sql) throws SQLException {
//		QueryRunner run = new QueryRunner();
//		return run.update(conn, sql);
//	}

	/**
	 * Efetua batch update.
	 * 
	 * @param conn connection
	 * @param sql instrução a ser executada
	 * @param params lista de parametros
	 * @return numero de linhas afetadas
	 * @throws SQLException exception
	 */
//	public static int[] batch(Connection conn, String sql, Object[][] params) throws SQLException {
//		QueryRunner run = new QueryRunner();
//		return run.batch(conn, sql, params);
//	}

	/**
	 * Retorna parametro com clausula '%'.
	 * 
	 * @param parametro
	 *            parametro
	 * @return String likeParameter
	 */
	public static String getLikeParameter(String parametro) {
		if (parametro != null) {
			return "%" + parametro + "%";
		}
		return null;
	}
	
	/**
	 * Retorna parametro com clausula '%'.
	 * 
	 * @param parametro
	 *            parametro
	 * @return String likeParameter
	 */
	public static String getLikeParameterASCII(String parametro) 
	{
		if (StringUtils.isNotBlank(parametro)) {
			
			parametro = Normalizer.normalize(parametro, Normalizer.Form.NFD).replaceAll("[^\\p{ASCII}]", "");
			return "%".concat(parametro.toUpperCase().trim()).concat("%");
		}

		return parametro;
	}
	
	/**
	 * Retorna parametro com clausula '% à esquerda'.
	 * 
	 * @param parametro
	 * @return String likeParameter
	 */
	public static String getLikeParameterLeft(String parametro) {
		
		if (StringUtils.isNotBlank(parametro)) {

			return "%".concat(parametro.toUpperCase().trim());
		}
		
		return parametro;
	}

	/**
	 * Retorna parametro com clausula '% à direita'.
	 * 
	 * @param parametro
	 * @return String likeParameter
	 */
	public static String getLikeParameterRight(String parametro) {
		
		if (StringUtils.isNotBlank(parametro)) {
			
			return parametro.toUpperCase().trim().concat("%");
		}
		
		return parametro;
	}
	
	/**
	 * Retorna parametro com clausula '%'.
	 * 
	 * @param parametro
	 *            parametro
	 * @return String likeParameter
	 */
	public static String getParameterASCII(String parametro) 
	{
		if (StringUtils.isNotBlank(parametro)) {
			parametro = Normalizer.normalize(parametro, Normalizer.Form.NFD).replaceAll("[^\\p{ASCII}]", "");
			return parametro.toUpperCase().trim();
		}
		
		return parametro;
	}
	

	/**
	 * Retorna string na seguinte sintaxe:
	 * xmlexists('$c/AdesaoMunicipioVO/municipioVO[cdIbge = "5200050"]' passing
	 * au.DS_DADOS_XML as "c").
	 * 
	 * @param xml xml a ser processado
	 * @param colunaBanco coluna na tabela
	 * @return retorno
	 */
	public static String getXmlExistsDB2(String xml, String colunaBanco) {
		String retorno = null;
		try {
			if (StringUtils.isNotEmpty(xml) && StringUtils.isNotEmpty(colunaBanco)) {
				retorno = "xmlexists('$root/" + xml + "' passing " + colunaBanco + " as \"root\")";

				return retorno;
			}
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
		return retorno;
	}
	
	/**
	 * retorna a query xml DB2
	 * @param xml arquivo xml
	 * @param colunaBanco coluna na tabela
	 * @return retorno
	 */
	public static String getXmlQueryDB2(String xml, String colunaBanco) {
		String retorno = null;
		try {
			if (StringUtils.isNotEmpty(xml) && StringUtils.isNotEmpty(colunaBanco)) {
				retorno = "xmlquery('$root/" + xml + "/text()' passing " + 
					colunaBanco + " as \"root\")";

				return retorno;
			}
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
		return retorno;
	}

	/**
	 * 
	 * @param pathXml path xml
	 * @param valor valor
	 * @param operador operador
	 * @return retorno
	 */
	public static String getXPathDB2(String pathXml, String valor, String operador) {
		String pathXmlLocal = pathXml;
		String retorno = null;
		try {
			if (StringUtils.isNotEmpty(pathXmlLocal)) {
				pathXmlLocal = pathXmlLocal.replaceAll("\\\\", "/");
				String primeiraParte = pathXmlLocal.substring(0, pathXmlLocal.lastIndexOf('/'));
				String ultimoElemento = pathXmlLocal.substring(pathXmlLocal.lastIndexOf('/') + 1, 
						pathXmlLocal.length());
				ultimoElemento = "[" + ultimoElemento + " " + operador + " \"" + 
					valor + "\"]";

				retorno = primeiraParte + ultimoElemento;
				return retorno;
			}
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
		return retorno;
	}

	/**
	 * 
	 * @param pathXml
	 *            pathXml
	 * @param valor
	 *            valor
	 * @return String
	 */
	public static String getXPathDB2(String pathXml, String valor) {
		String retorno = null;
		try {
			return SQLUtil.getXPathDB2(pathXml, valor, "=");
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
		return retorno;
	}
	
	/**
	 * 
	 * @param pathXml path xml
	 * @return retorno
	 */
	public static String getXPathDB2(String pathXml) {
		String pathXmlLocal = pathXml;
		try {
			if (StringUtils.isNotEmpty(pathXmlLocal)) {
				pathXmlLocal = pathXmlLocal.replaceAll("\\\\", "/");
				return pathXmlLocal;
			}
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
		return null;
	}
}